package org.takeback.chat.service.admin;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Stack;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.takeback.chat.entity.GcRoom;
import org.takeback.chat.entity.PubUser;
import org.takeback.chat.store.room.Room;
import org.takeback.chat.store.room.RoomStore;
import org.takeback.chat.store.user.RobotUser;
import org.takeback.chat.store.user.UserStore;
import org.takeback.core.service.MyListService;
import org.takeback.dao.BaseDAO;
import org.takeback.util.BeanUtils;
import org.takeback.util.converter.ConversionUtils;
import org.takeback.util.exception.CodedBaseRuntimeException;
import org.takeback.util.exp.ExpressionProcessor;

@Service("robotAdminService")
public class RobotService extends MyListService {
	@Autowired
	RoomStore roomStore;
	@Autowired
	private UserStore userStore;
	private Map<Integer, Thread> ts = new HashMap();
	private Stack<RobotUser> freeRobots = null;
	private Map<String, Stack<RobotUser>> workingRobots = new HashMap();

	@Transactional(readOnly = true)
	public Map<String, Object> list(Map<String, Object> req) {
		String entityName = "GcRoom";
		if (StringUtils.isEmpty(entityName)) {
			throw new CodedBaseRuntimeException(404, "missing entityName");
		}
        int limit = (int) req.get(LIMIT);
        int page = (int) req.get(PAGE);
		List<?> cnd = (List) ConversionUtils.convert(req.get(CND), List.class);
		String filter = null;
		if (cnd != null) {
			filter = ExpressionProcessor.instance().toString(cnd);
		}
        String orderInfo = (String) req.get("id");
		List<GcRoom> ls = this.dao.query(entityName, filter, limit, page, orderInfo);
		afterList(ls);

		List<Map> list = new ArrayList();
		for (int i = 0; i < ls.size(); i++) {
			GcRoom room = (GcRoom) ls.get(i);
			Map<String, Object> m = new HashMap();
            int num = (this.workingRobots.get(room.getId()) == null) ? 0 : this.workingRobots.get(room.getId()).size();
			m.put("id", room.getId());
			m.put("roomName", room.getName());
            m.put("robotNum", num);
			list.add(m);
		}
		long count = this.dao.totalSize(entityName, filter);
		Map<String, Object> result = new HashMap();
		result.put("totalSize", Long.valueOf(count));
		result.put("body", list);
		return result;
	}

	@Transactional(readOnly = true)
	public Object load(Map<String, Object> req) {
		Object pkey = req.get("id");
		GcRoom room = (GcRoom) this.dao.get(GcRoom.class, pkey.toString());
		Map<String, Object> entity = new HashMap();
		entity.put("id", room.getId());
		entity.put("roomName", room.getName());
        entity.put("robotNum", (this.workingRobots.get(room.getId()) == null) ? 0 : this.workingRobots.get(room.getId()).size());
		return entity;
	}

	//初始化添加机器人
	@Transactional
	public void save(Map<String, Object> req) {
		Map<String, Object> data = (Map) req.get("data");
		String id = (String) data.get("id");
		int num = Integer.valueOf((String) data.get("robotNum")).intValue();
		Room rm = (Room) this.roomStore.get(id);
		int curNum = this.workingRobots.get(id) == null ? 0 : ((Stack) this.workingRobots.get(id)).size();
		int change = num - curNum;
		Stack<RobotUser> stack;
		if (change > 0) {
			List<RobotUser> robots = getFreeRobots(change);
			stack = (Stack) this.workingRobots.get(rm.getId());
			if (stack == null) {
				stack = new Stack();
				this.workingRobots.put(rm.getId(), stack);
			}
			for (RobotUser ru : robots) {
				ru.setRoom(rm);
				this.userStore.reload(ru.getId());
				rm.join(ru);
				stack.push(ru);
				Thread t = new Thread(ru);
				this.ts.put(ru.getId(), t);
				t.start();
			}
		} else {
			change = Math.abs(change);
			stack = (Stack) this.workingRobots.get(rm.getId());
			if (stack == null) {
				return;
			}
			for (int i = 0; i < change; i++) {
				RobotUser r = (RobotUser) stack.pop();
				Thread t = (Thread) this.ts.get(r.getId());
				try {
					t.interrupt();
				} catch (Exception e) {
					e.printStackTrace();
				}
				this.ts.remove(r.getId());
				rm.left(r);
				this.freeRobots.add(r);
			}
		}
	}

	@Transactional(readOnly = true)
	public List<RobotUser> getFreeRobots(int num) {
		if (this.freeRobots == null) {
			this.freeRobots = new Stack();
			String hql = "from PubUser where userType=9  order by id asc";
			List<PubUser> rs = this.dao.findByHql(hql);
			for (int i = 0; i < rs.size(); i++) {
				RobotUser r = (RobotUser) BeanUtils.map(rs.get(i), RobotUser.class);
				this.freeRobots.push(r);
			}
		}
		if (this.freeRobots.size() < num) {
			throw new CodedBaseRuntimeException("空闲机器人:" + this.freeRobots.size() + "个");
		}
		List<RobotUser> robots = new ArrayList();
		for (int i = 0; i < num; i++) {
			robots.add(this.freeRobots.pop());
		}
		return robots;
	}
}
